View Javadoc
1   package edu.jiangxin.apktoolbox.file.password.recovery.category.dictionary.singlethread;
2   
3   import edu.jiangxin.apktoolbox.file.core.EncoderDetector;
4   import edu.jiangxin.apktoolbox.file.password.recovery.RecoveryPanel;
5   import edu.jiangxin.apktoolbox.file.password.recovery.category.ICategory;
6   import edu.jiangxin.apktoolbox.utils.Utils;
7   import org.apache.logging.log4j.LogManager;
8   import org.apache.logging.log4j.Logger;
9   
10  import javax.swing.*;
11  import java.io.*;
12  import java.util.Optional;
13  import java.util.function.Function;
14  import java.util.function.Predicate;
15  import java.util.stream.Stream;
16  
17  public class DictionarySingleThreadProxy implements ICategory {
18      private static final Logger logger = LogManager.getLogger(DictionarySingleThreadProxy.class.getSimpleName());
19  
20      private boolean isCancelled;
21  
22      private static class DictionarySingleThreadProxyHolder {
23          private static final DictionarySingleThreadProxy instance = new DictionarySingleThreadProxy();
24      }
25  
26      private DictionarySingleThreadProxy() {
27      }
28  
29      public static DictionarySingleThreadProxy getInstance() {
30          return DictionarySingleThreadProxy.DictionarySingleThreadProxyHolder.instance;
31      }
32  
33      private String startAndGet(String charsetName, RecoveryPanel panel) {
34          isCancelled = false;
35          Predicate<String> isRecoveringPredicate = password -> (!isCancelled);
36          Function<String, Stream<String>> generator = password -> {
37              panel.setCurrentPassword(password);
38              panel.increaseProgressBarValue();
39              return Stream.of(password.toLowerCase(), password.toUpperCase());
40          };
41          Predicate<String> verifier = panel.getCurrentFileChecker()::checkPassword;
42          try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(panel.getDictionaryFile()), charsetName))) {
43              // java.util.stream.BaseStream.parallel can not increase the speed in test
44              Optional<String> password = br.lines().takeWhile(isRecoveringPredicate).flatMap(generator).filter(verifier).findFirst();
45              return password.orElse(null);
46          } catch (FileNotFoundException e) {
47              logger.info("FileNotFoundException");
48          } catch (IOException e) {
49              logger.info("IOException");
50          }
51          return null;
52      }
53  
54      @Override
55      public void start(RecoveryPanel panel) {
56          File dictionaryFile = panel.getDictionaryFile();
57          if (!dictionaryFile.isFile()) {
58              JOptionPane.showMessageDialog(panel, "Invalid dictionary file");
59              return;
60          }
61          String charsetName = EncoderDetector.judgeFile(dictionaryFile.getAbsolutePath());
62          logger.info("dictionary file: {}, charset: {}", dictionaryFile.getAbsolutePath(), charsetName);
63          if (charsetName == null) {
64              JOptionPane.showMessageDialog(panel, "Invalid charsetName");
65              return;
66          }
67          panel.resetProgressMaxValue(Utils.getFileLineCount(dictionaryFile));
68          String password = startAndGet(charsetName, panel);
69          panel.showResultWithDialog(password);
70      }
71  
72      @Override
73      public void cancel() {
74          isCancelled = true;
75      }
76  }